<?php
namespace app\api\controller;


use GuzzleHttp\Client;
use think\facade\Log;
use think\Antiaddiction;

class PlayerAuth
{
    private $appId;
    private $secret_key;
    private $bizId;

    /**
     * AntiAddictionService constructor.
     * @param $app_id
     * @param $secret_key
     * @param $biz_id
     */
    public function __construct() {
        $this->appId = "a0148ef2d30c4c1ba04e84d44614fa07"; // a0148ef2d30c4c1ba04e84d44614fa07
        $this->secret_key = "5d37fb0a9d397ce2d549231d568bbe46"; //5d37fb0a9d397ce2d549231d568bbe46 db5c44a6ec5d687d2bf5d9f1d2474953
        $this->bizId = "1199002334";// 1199002334
    }

    /**
     * 实名认证接口
     * @param $ai
     * @param $name
     * @param $id_num
     */
    public function checkIdCard($name, $id_num, $test_code = '') {
        $ai = md5($this->appId .$id_num);
        $client = new Client();
        $body = [
            'ai' => $ai,
            'name' => $name,
            'idNum' => $id_num
        ];
        $uri = 'https://api.wlc.nppa.gov.cn/idcard/authentication/check';
//        $uri = 'https://wlc.nppa.gov.cn/test/authentication/check';
        if($test_code) {
            $uri = 'https://wlc.nppa.gov.cn/test/authentication/check/'.$test_code;
        }
        $header = $this->getHeader($body, []);
        $response  = $client->request('POST', $uri, [
            'headers' => $header['header'],
            'json' => $header['encrypted_body'],
            'timeout' => 5
        ]);
        $content = $response->getBody()->getContents();
        Log::info("Anti Addiction - checkIdCard: ".$content);
        return json_decode($content, true);
    }

    /**
     * 实名认证结果查询
     * @param $ai
     */
    public function queryIdCard($id_number, $test_code = '') {
        $ai = md5($this->appId . $id_number);

        $client = new Client();
        $query_params = [
            'ai' => $ai
        ];
        $header = $this->getHeader([], $query_params);
        $uri = 'http://api2.wlc.nppa.gov.cn/idcard/authentication/query';
//        $uri = 'https://wlc.nppa.gov.cn/test/authentication/query';
        if($test_code) {
            $uri = 'https://wlc.nppa.gov.cn/test/authentication/query/'.$test_code;
        }
        try {
            $response  = $client->request('GET', $uri, [
                'headers' => $header['header'],
                'query' => $query_params,
                'timeout' => 5
            ]);
        } catch (\GuzzleHttp\Exception\GuzzleException $e) {
            Log::error("Anti Addiction - queryIdCard: ". $e->getMessage());
            return false;
        }

        $content = $response->getBody()->getContents();
        Log::info("Anti Addiction - queryIdCard: ".$content);

        return json_decode($content, true);
    }

    /**
     * 上报游戏用户上下线行为数据
     * @param $collections
     * @return mixed
     */
    public function reportLogInOut($collections, $test_code = '') {
        $collections['si'] = md5($this->appId . $collections['pi']);
        $client = new Client();
        $header = $this->getHeader(['collections' => $collections], []);
        // 记录完整的请求信息
        Log::debug("Anti Addiction - Full Request", [
            'headers' => $header['header'],
            'body' => $header['encrypted_body']
        ]);
        $uri = 'http://api2.wlc.nppa.gov.cn/behavior/collection/loginout';
        if($test_code) {
            $uri = 'https://wlc.nppa.gov.cn/test/collection/loginout/'.$test_code;
        }
        try {
            $response  = $client->request('POST', $uri, [
                'headers' => $header['header'],
                'data' => $header['encrypted_body'],
                'timeout' => 5
            ]);
        } catch (\GuzzleHttp\Exception\GuzzleException $e) {
            Log::error("Anti Addiction - reportLogInOut: ". $e->getMessage());
            return false;
        }

        $content = $response->getBody()->getContents();
        dump($content);exit;
        Log::info("Anti Addiction - reportLogInOut: ".$content);
        return json_decode($content, true);
    }


    /**
     * 对请求报文体进行加密
     * @param $body
     * @return string
     */
    private function bodyEncrypt($body)
    {
        Log::info("Anti Addiction - Encrypt Before:" .json_encode($body));
        $key = hex2bin($this->secret_key);
        $cipher = "aes-128-gcm";
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = openssl_random_pseudo_bytes($ivlen);

        $tag = null;
        $encrypt = openssl_encrypt(json_encode($body), $cipher, $key, OPENSSL_RAW_DATA,$iv,$tag);
        $str = bin2hex($iv) .  bin2hex($encrypt) . bin2hex($tag);
        $after = base64_encode(hex2bin($str));
        Log::info("Anti Addiction - Encrypt After:" .$after);
        return $after;
    }

    /**
     * 接口签名
     * @param $body
     * @param $query_params
     */
    private function sign($body, $query_params, $timestamps)
    {
        if(!empty($body)) {
            $encrypted_body = json_encode(['data' => $this->bodyEncrypt($body)]);
        } else {
            $encrypted_body = '';
        }

        Log::info("Anti Addiction - Encrpyted Body:".$encrypted_body);

        $sys_params = [
            'appId' => $this->appId,
            'bizId' => $this->bizId,
            'timestamps' => $timestamps
        ];
        $final_params = array_merge($sys_params, $query_params);
        ksort($final_params);

        $str_params = '';
        foreach ($final_params as $k => $v) {
            $str_params .= $k.$v;
        }
        $str_params .= $encrypted_body;
        $str_params = $this->secret_key.$str_params;

        Log::info("Anti Addiction - Sign Before:".$str_params);
        $hash = hash('sha256', $str_params);

        Log::info("Anti Addiction - Sign After:".$hash);
        return [
            'sign' => $hash,
            'encrypted_body' => json_decode($encrypted_body, true)
        ];
    }


    /**
     * 请求头构建
     * @param $body
     * @param $query_params
     * @return array
     */
    private function getHeader($body, $query_params) {
        list($msec, $sec) = explode(' ', microtime());
        $timestamps = sprintf('%d', (floatval($msec) + floatval($sec)) * 1000);

        $sign_data = $this->sign($body, $query_params, $timestamps);
        $header = [
            'Content-Type' => 'application/json;charset=utf-8',
            'appId' => $this->appId,
            'bizId' => $this->bizId,
            'timestamps' => $timestamps,
            'sign' => $sign_data['sign']
        ];



        Log::info("Anti Addiction - Header:". json_encode($header));

        return [
            'header' => $header,
            'encrypted_body' => $sign_data['encrypted_body']
        ];

    }


}